home *** CD-ROM | disk | FTP | other *** search
- INCLUDE \ASM\INCLUDE\BIOS.INC
- INCLUDE DEFS.INC
-
- SOUND EQU 61h
- TIMER EQU 42h
- SPK_ON EQU 3
-
- VECTOR1 EQU 09h ; BIOS keyboard handler
- IROW EQU 5 ; Starting row,col of window
- ICOL EQU 10
- IHEIGHT EQU 5 ; Size of window
- IWIDTH EQU 63
-
- ; status constants
- MAX_DEST EQU 16 ; length of destination field
- MAX_MSG EQU IWIDTH - 2 ; length of message field
- DEST EQU 0 ; which field is active?
- MSG EQU 0FFFFh
-
- ; key codes
- UP EQU 4800h ; up arrow
- DN EQU 5000h ; down arrow
- LEFT EQU 4B00h ; left arrow
- RIGHT EQU 4D00h ; right arrow
- RETURN EQU 1C0Dh ; return key
- BACK EQU 0E08h ; backspace key
- INSERT EQU 5200h
- DELETE EQU 5300h
- HOME EQU 4700h
- ENDKEY EQU 4F00h ; End key
- ESCAPE EQU 011Bh ; Escape key
-
- msv SEGMENT
- ASSUME CS:msv
- ASSUME DS:msv
- ASSUME ES:msv
- ASSUME SS:NOTHING
- ORG 0
- SEG_ORG EQU $
- ORG 100h
- main PROC FAR
- start: jmp init ; Do initialization section
-
- ;*******************************************************************
- ; LANOS VECTOR TSR portion of Message handler --
- ; The LANOS portion simply increments a message received flag and
- ; exits, leaving the actual processing of the message to an
- ; interrupt.
- ;*******************************************************************
- MSV_entry: jmp first ; skip data area
- msg_flag dw 0
- old_msr dd ?
-
- ;************************************************************************
- ; Start of actual LANOS message handler. Note that this handler DOES NOT
- ; call the previously chained vector -- while the intercom is popped up,
- ; no other message handling services will be activated.
- ;************************************************************************
- first:
- mov cs:msg_flag,1 ; set the message received flag
- iret ; return to caller
-
- ; ********************************************************************
- ; Interrupt 09 - Keyboard interrupt handler
- ; Thanks to Joe and Sam for demonstrating the right way to do it!
- ; ********************************************************************
- INT09_entry:
- push ax
- cmp cs:busy,0 ; are we already popped up?
- jnz Done_09 ; if so, continue
-
- in al,60h ; Read the character from the kbd
- CMP AL,CS:hotkey ; is it for us?
- JNZ Done_09 ; if not, continue
-
- ; Check the keyboard status bits to see if it's for us
- PUSH DS
- MOV AX,40H ; POINT TO THE BIOS
- MOV DS,AX
- MOV AL,DS:17H ; Get kbd status byte
- POP DS
- AND AL,CS:kbd_bits ; ARE THESE BITS ON?
- CMP AL,CS:kbd_bits ; WELL?
- JNZ Done_09 ; NOPE NOT AT THIS TIME
-
- ; reset the keyboard
- IN AL,61H ; GET KBD CONTROL CODE
- MOV AH,AL
- OR AL,80H ; SET RESET BIT
- OUT 61H,AL ; SEND RESET BACK
- MOV AL,AH ; GET BACK THE CONTROL CODE
- OUT 61H,AL ; RESET DONE
- MOV AL,20H ; RESET HIGHEST IUS
- OUT 20H,AL
-
- inc cs:request ; issue a pop up request
- pop ax
- IRET ; back to regularly scheduled program
-
- Done_09:
- POP AX
- JMP CS:old_vector1 ; CONTINUE ON AS IF WE AREN'T HERE
-
- ;*****************************************************************************
- ; Interrupt E0 handler --- this is apparently something that LANtastic uses
- ; internally to indicate when DOS is safe.
- ;*****************************************************************************
- INT_E0 DD 0
- DOSFREE:
- PUSHF
- CALL CS:old_vector2 ; give everyone else a chance...
-
- cmp cs:request,0 ; have our services been requested?
- jz Done_E0 ; If not, skip this stuff
- CMP CS:busy,0 ; Are we already busy?
- JNZ Done_E0 ; If so, skip this stuff
-
- ; Activate the pop up routine
- dec cs:request ; cancel previous request
- inc cs:busy ; set busy flag
- call pop_up
- dec cs:busy
-
- Done_E0:
- IRET
-
- ;***********************************************************************
- ; Pop-up intercom
- ; When we're popped up, an Esc keypress will take us back to normal
- ; processing
- ;***********************************************************************
- pop_up PROC near
- jmp get_msg ; bypass data area
-
- ; housekeeping stuff and screen data area.
- db '■S' ; ID string
- color db 70h ; Default window color
- hotkey db 23 ; Activation key (I for now)
- kbd_bits db 8 ; Alt
- busy db 0 ; TSR status flag
- request db 0 ; TSR activation request flag
- screen_data dw (IHEIGHT * IWIDTH) DUP (?)
- from db 'From: ',0 ; Onscreen prompts and instructions
- toquit db 'Press Esc to exit',0
- old_vector1 dd ? ; old int vector
- old_vector2 dd ?
- old_cursor dw ? ; old cursor position
- msg_state db ? ; old message processing flag
-
- ; program status variables
- state db ? ; current field id
- ins_flag db 0 ; insert key state flag
- d_index field_desc <0,0,16,OFFSET buffer.MB_machine>
- m_index field_desc <0,0,61,OFFSET buffer.MB_text>
- c_field dw 0 ; pointer to current field descriptor
- done db 0 ; completion flag
- buffer message_buffer <> ; message buffer for internal use
- inbuffer message_buffer <> ; buffer for incoming messages
- prompt1 db "To:─────",0 ; prompt text messages
- prompt2 db "Message:",0
-
- ; stack information
- old_stk_seg dw ? ; Calling program's stack info
- old_b_ptr dw ?
- old_stk_ptr dw ?
- new_stk_seg dw ?
- new_stk_ptr dw OFFSET TOS
- dw 80 dup (?) ; local stack data area
- TOS equ $
-
- get_msg:
- @NewStack ; replace stack and save regs
- push cs ; set all seg regs to current CS
- push cs
- pop es
- pop ds
-
- ; save calling cursor information
- IC1:
- mov ah,3 ; read cursor info
- xor bh,bh ; for page 0
- int 10h
- mov cs:old_cursor,dx ; save cursor info
-
- ;
- ; Replace the LANOS message service with our message handler
- ;
-
- ; Save the message processing flag
- mov ax,5F9Ah
- int 21h
- mov cs:msg_state,dl
-
- ; Get addresss of old LANOS message handler
- mov ax,5FE2h ; Get old vector address
- int 21h
- mov word ptr old_msr,bx ; Save the location of the old vector
- mov word ptr old_msr+2,es
-
- ; Set MSR vector to our routine
- mov ax,cs ; segment address of our MSR
- mov es,ax
- mov bx,OFFSET MSV_entry ; offset of MSR
- mov ax,5FE3h ; set MSR vector function
- int 21H
-
- ;
- ; Tell message handler not to beep
- ;
- mov ax,5F9Bh ; set message processing flag
- mov dl,2 ; deliver, but no beep
- int 21h
-
- ;
- ; save underlying screen and draw intercom window
- ;
- mov di, OFFSET screen_data ; point to save area
- mov dh,IROW ; starting screen row
- mov cx,IHEIGHT
-
- doRow: ; For each row...
- push cx ; save number of rows
- mov dl,ICOL ; starting column on screen
- call CURSOR ; move cursor to row start
- mov cx,IWIDTH ; number of columns
-
- DoCol: ; For each character
- push cx ; save char count
- @GetChAtr 0 ; Get the char and attribute
- stosw ; move it to the save area
-
- inc dl ; move cursor
- call CURSOR
-
- pop cx ; retrieve char count
- loop SHORT DoCol ; go back for next char
-
- inc dh ; point to next screen row
- pop cx ; retrieve row count
- loop SHORT DoRow
-
- ; Draw intercom window
- DRAW_LINE '┌','─','╖',IROW
-
- MOVE_CURSOR IROW,ICOL+1
- mov di, OFFSET from
- call PRT_STR
-
- DRAW_LINE '│',' ','║',IROW+1
-
- DRAW_LINE '├','─','╢',IROW+2
-
- DRAW_LINE '│',' ','║',IROW+3
-
- DRAW_LINE '╘','═','╝',IROW+4
-
- MOVE_CURSOR IROW+4,ICOL+45
- mov di, OFFSET toquit
- call PRT_STR
-
- ;
- ; Initialize variables
- ;
- push cs ; set all seg regs to current CS
- push cs
- pop es
- pop ds
-
- mov done,0
-
- mov c_field,OFFSET d_index ;destination field
-
- ;
- ; Get user input
- ;
- mov dh,IROW + 2 ; display field name prompt
- mov dl,ICOL + 1
- call CURSOR
- mov di,OFFSET prompt1
- call PRT_STR
-
- mov dh,IROW + 3 ; display destination prompt
- mov dl,ICOL + 1
- call CURSOR
- mov di,OFFSET buffer.MB_machine
- call PRT_STR
-
- mov cs:state,DEST ; set field to destination
-
- mov dh,IROW + 3 ; move cursor to start of field
- mov dl,ICOL + 1
- add dl,d_index.FD_index ; move to last cursor pos
- mov msg_flag,1 ; set up to display last message
-
- Get_input:
- cmp msg_flag,1 ; see if a message is ready
- jne GI1
- call SHOW_MESSAGE ; if we've got one, show it.
- GI1:
- call CURSOR ; move cursor to appropriate place
- mov ax,0100h ; get keyboard status fn.
- int 16h
- jz Get_input ; if not, go back
-
- xor ax,ax ; Read keyboard char fn.
- int 16h
- ;
- ; Process each keystroke
- ;
- cmp ax,UP
- jne N1
- jmp Toggle
- N1: cmp ax,DN
- jne N2
- Toggle: ; switch fields
- cmp state,DEST ; are we in destination state?
- jne toggle2 ; if not, go to other switch
-
- call CLEAR_FIELD ; clear the field
- not state ; switch to message state
- mov c_field, OFFSET m_index ; switch to correct field desc.
-
- mov dh,IROW + 3 ; display message text
- mov dl,ICOL + 1
- call CURSOR
- mov di, OFFSET buffer.MB_text
- call PRT_STR
-
- mov dh,IROW + 2 ; display message prompt
- mov dl,ICOL + 1
- CALL CURSOR
- mov di,OFFSET prompt2 ; display MESSAGE: prompt
- call PRT_STR
-
- mov dh,IROW + 3 ; move cursor to proper spot
- mov dl,ICOL + 1
- mov si,c_field ; get address of field record
- add dl,[si].fd_index
- call CURSOR
- jmp Break
- Toggle2:
- call CLEAR_FIELD ; clear the field
-
- not state ; switch to message state
- mov c_field, OFFSET d_index ; switch to correct field desc.
-
- mov dh,IROW + 3 ; display destination
- mov dl,ICOL + 1
- call CURSOR
- mov di, OFFSET buffer.MB_machine
- call PRT_STR
-
- mov dh,IROW + 2 ; display destination prompt
- mov dl,ICOL + 1
- call CURSOR
- mov di,OFFSET prompt1
- call PRT_STR
-
- mov dh,IROW + 3 ; move cursor to proper spot
- mov dl,ICOL + 1
- mov si,c_field ; get address of field record
- add dl,[si].fd_index ; get current cursor position
- call CURSOR
- jmp Break
-
- N2: cmp ax,LEFT
- jne N3
- mov si,c_field ; check cursor position
- cmp [si].FD_index,0 ; if at left edge, do nothing
- jne LCONT
- jmp Break
- LCONT:
- dec [si].FD_index ; move one position left
- dec dl ; move cursor
- jmp Break
- N3: cmp ax,RIGHT
- jne N4
- mov si,c_field ; check cursor position
- mov ah,[si].FD_index
- cmp ah,[si].FD_maxlen
- jl RCONT
- jmp Break
- RCONT: ; if at right edge, do nothing
- inc [si].FD_index ; move one position right
- inc dl ; move cursor
- jmp Break
- N4: cmp ax,BACK
- jne N5
- mov si,c_field ; check cursor position
- cmp [si].FD_index,0 ; if at left edge, do nothing
- jg BCONT
- jmp Break
- BCONT:
- dec [si].FD_index ; move one column left
- dec dl ; move cursor too
- call CURSOR
-
- xor cx,cx
- mov cl,[si].FD_index ; current pointer position
- mov si,[si].FD_data ; offset of start of current string
- add si,cx ; point to current position
-
- call DELETE_CHAR
- jmp Break
-
- N5: cmp ax,RETURN
- jne N6
- ; see if we're ready to send a message
- cmp d_index.FD_length,0 ; see if destination is set
- jg RET1
- jmp Toggle ; if not, just switch fields
- RET1:
- cmp m_index.FD_length,0 ; see if message is ready
- jg RET2 ; if not, just switch fields
- jmp Toggle
-
- ; if so, compose the message and send it
- RET2:
- mov ax,5F98H ; send message interrupt
- mov si,OFFSET buffer ; message buffer
- int 21h ; send message
-
- ; clear fields and get ready for next message
- call CLEAR_FIELD
- mov m_index.FD_length,0 ; zero pointers an length for message
- mov m_index.FD_index,0
- mov d_index.FD_length,0 ; zero pointers and length for dest
- mov d_index.FD_index,0
- mov buffer.MB_machine,0 ; zero message and dest buffers
- mov buffer.MB_text,0
- mov state,MSG
- jmp Toggle ; toggle state to DEST again...
- jmp Break
- N6: cmp ax,INSERT
- jne N7
- not ins_flag ; toggle insert flag
- jmp Break
- N7: cmp ax,DELETE
- jne N8
- mov si,c_field
- cmp [si].FD_length,0 ; if length is 0, nothing to delete
- jg DELCONT
- jmp Break
- DELCONT:
- xor cx,cx
- mov cl,[si].FD_index ; current pointer position
- mov si,[si].FD_data ; offset of start of current string
- add si,cx ; point to current position
-
- call DELETE_CHAR
- jmp Break
- N8: cmp ax,HOME
- jne N9
- xor bx,bx ; get us a zero to work with
- mov si,c_field ; get current field address
- mov [si].FD_index,bl
- mov dl,ICOL + 1 ; reset current cursor position
- jmp Break
- N9: cmp ax,ESCAPE
- jne N10
- mov done,1
- jmp Break
- N10: cmp ax,ENDKEY
- jne Default
- mov si,c_field
- mov bl,[si].FD_length
- mov [si].FD_index,bl
- mov dl,ICOL + 1
- add dl,bl
- jmp Break
- Default:
- mov si,c_field
- mov bl,[si].FD_length
- mov bh,[si].FD_maxlen
- cmp bl,bh ; see if we've hit the end of field
- jge Break ; if so, do nothing
-
- cmp state,DEST ; see if we're in destination field
- jne DEFCON ; if not, don't shift
- call UPCASE
-
- DEFCON:
- cmp ins_flag,0 ; see if we're in insert state
- je OVERWRITE ; if not, overwrite
- call INSERT_CHAR
- jmp Break
-
- OVERWRITE:
- mov ah,[si].FD_index ; save the character
- CALL STORE_CHAR
-
- PUTC al,1 ; write character
- inc dl ; increment cursor position
- mov cl,[si].FD_index ; get current position
- inc cl ; increment char pointer
- mov [si].FD_index,cl ; save new pointer
-
- cmp cl,[si].FD_length ; are we appending to the string?
- jl Break ; if not, we're done
-
- mov ah,[si].FD_length ; otherwise, get length pointer
- inc ah ; increment string length
- mov [si].FD_length,ah ; save new length
- xor al,al ; save a terminating NULL char
- CALL STORE_CHAR
-
- Break:
- cmp cs:done,1
- je shutdown
- jmp get_input
-
- shutdown:
- ;
- ; Restore screen data
- ;
- mov si, OFFSET screen_data ; point to save area
-
-
- mov dh,IROW
- mov cx,IHEIGHT ; number of rows to do
-
- doRow1: ; For each row...
- push cx ; save number of rows
- mov dl,ICOL ; starting column on screen
- call CURSOR ; move cursor to row start
- mov cx,IWIDTH ; number of columns
-
- DoCol1: ; For each character
- push cx ; save char count
-
- lodsw ; get next word from save area
- @PutChAtr al,ah,0,1 ; write next picture char
-
- inc dl ; move cursor
- call CURSOR
-
- pop cx ; retrieve char count
- loop SHORT DoCol1 ; Go back for next char
-
- inc dh ; point to next row
- pop cx ; retrieve row count
- loop SHORT DoRow1 ; Go back for next char
-
- ;
- ; Restore previous LANOS message handler.
- ;
-
- ; Set MSR vector to original routine
- mov ax,word ptr old_msr+2 ; segment addr of old routine
- mov es,ax
- mov bx,word ptr old_msr ; offset of old routine
- mov ax,5FE3h ; set MSR vector fn.
- int 21H
-
- ;
- ; Restore the message processing flag
- ;
- mov ax,5F9Bh ; set message processing flag
- mov dl,cs:msg_state ; back to it's previous state
- int 21h
-
-
- ; restore cursor to original position
- mov ah,2 ; set cursor position
- mov bh,0 ; for page 0
- mov dx,cs:old_cursor
- int 10h
-
- bypass:
- @OldStack ; restore caller's stack
- ret ; return to caller
- pop_up ENDP
-
- ;*********************************************************************
- ; Subroutines
- ;********************************************************************
- ; Move cursor -- row in dh, col in dl
- CURSOR PROC NEAR
- push ax
- push bx
- push cx
-
- @SetCurPos dl,dh,0
-
- pop cx
- pop bx
- pop ax
- ret
- CURSOR ENDP
- PRT_STR PROC NEAR
- ;
- ; Write ASCIIZ string pointed to by ES:DI at current cursor position
- ;
- L3:
- mov al,es:[di] ; get the character
- or al,al ; See if it's a zero
- jz L4 ; Yes- we're done
- mov bx,7 ; display page 0, fg color 7
- mov ah,0Eh ; Write char / tty mode
- int 10h ; Display the character
- inc di ; get the next char
- jmp short L3
- L4:
- ret
- PRT_STR ENDP
-
- CLEAR_FIELD PROC NEAR
- ;
- ; clear the input field
- ;
- mov dh,IROW + 3
- mov dl,ICOL + 1
- call CURSOR
-
- mov si,c_field
- xor cx,cx
- mov cl,[si].FD_maxlen
- PUTC ' ',cx
-
- mov dh,IROW + 3
- mov dl,ICOL + 1
- call CURSOR
-
- ret
- CLEAR_FIELD ENDP
-
- DELETE_CHAR PROC NEAR
- ;
- ; Gets rid of a the character in the asciiz string currently
- ; pointed to by DS:SI. Assumes that ES is also pointing to
- ; the string's segment. Handles all screen IO, assuming the
- ; cursor was positioned at the character to be deleted.
- ;
- push dx ; save starting cursor position
-
- mov di,si ; save offset of char to go
- push di ; save offset for printing later
-
- inc si ; skip the current char
- DL1:
- lodsb ; get the next char
- stosb ; save it in the previous slot
- cmp al,0 ; is a terminator?
- jne DL1 ; if not, go back for the next char
-
- pop di ; get the old string location back
- call PRT_STR ; print the modified string
- PUTC ' ',1
- pop dx ; restore starting cursor position
-
- mov si,c_field ; update housekeeping info
- dec [si].FD_length
-
- ret
- DELETE_CHAR ENDP
-
- STORE_CHAR PROC NEAR
- ;
- ; Store a character in the current field string. Takes the character
- ; in Al and the position in the string in AH. Uses the BX register
- ;
- push bx ; save the registers used
- push cx
-
- xor cx,cx ; clear CX ...
- mov cl,ah ; load w/ offset value
-
- mov bx,c_field
- mov bx,[bx].FD_data ; offset of string buffer
- add bx,cx ; + position in buffer
- mov [bx],al ; save character
-
- pop cx ; restore registers
- pop bx
- ret
- STORE_CHAR ENDP
-
- UPCASE PROC NEAR
- ;
- ; If the character in al is a lower case letter, convert to uppercase
- ;
- cmp al,97 ; compare to 'a'
- jl SHL1 ; if lower, return
- cmp al,122 ; compare to 'z'
- jg SHL1 ; if higher, return
- sub al,32 ; convert to uppercase
- SHL1:
- ret
- UPCASE ENDP
-
- INSERT_CHAR PROC NEAR
- ;
- ; Inserts the character currently in AL in the current string at the
- ; location indicated by AH. Assumes that ES is also pointing to the string's
- ; segment and that the cursor is located at the right spot.
- ;
- push dx ; save starting cursor position
-
- xor cx,cx ; point SI to correct location
- mov si,c_field
- mov cl,[si].FD_index
- mov si,[si].FD_data
- add si,cx
- mov di,si ; copy string pointer to DI
-
- IL1:
- mov ah,[si] ; old character in ah
- mov [si],al ; new char in al
- mov al,ah ; move old to new
-
- inc si ; move to next char position
- and ah,ah ; see if it's a zero
- jnz IL1 ; if not, go back for next one
-
- ; display the string
- CALL PRT_STR
-
- ; Update housekeeping information
- mov si,c_field
- inc [si].FD_index
- inc [si].FD_length
-
- pop dx ; restore cursor location
- inc dl
- ret
- INSERT_CHAR ENDP
-
- SHOW_MESSAGE PROC NEAR
- ;
- ; display message in message area
- ;
- push dx ; save current cursor loc
-
- mov ax,5F99h ; get last message fn.
- mov di,OFFSET inbuffer ; point to receive area
- int 21h ; get the message
-
- ;
- ; Display last received message and previous contents of message buffer
- ;
- mov dh,IROW ; display originator's name
- mov dl,ICOL + 7
- call CURSOR
- PUTC '─',16 ; clear field
- call CURSOR
- ; get rid of trailing spaces
- mov di, OFFSET inbuffer.MB_originator
- mov al,32 ; scan for spaces
- mov cx,16 ; max field length
- repnz scasb
- mov [di],ch ; terminate string
- ; print the string
- mov di, OFFSET inbuffer.MB_originator
- call PRT_STR
-
- ; display message text
- ; -- first make silly sound
- mov al,0B6h ; timer setup value
- out 43h,al ; tell timer a count's coming
- mov ax,397 ; frequency -- about 3000 hertz
- out 42h,al ; send the count
- mov al,ah
- out 42h,al
-
- xor ah,ah
- in al,SOUND ; turn on speaker
- or al,SPK_ON
- out SOUND,al
-
- mov dh,IROW + 1 ; display message text
- mov dl,ICOL + 1
- call CURSOR
- PUTC ' ',61
- call CURSOR
- mov di, OFFSET inbuffer.MB_text
- call PRT_STR
-
- ; turn off speaker
- in al,sound
- and al, NOT SPK_ON
- out sound,al
-
- pop dx ; restore cursor position
- mov msg_flag,0 ; reset received flag
- ret
- SHOW_MESSAGE ENDP
- ; write character in al at current cursor position
- ; char count should be in CX
- PUTCHAR PROC NEAR
- mov bl,color
- xor bh,bh
- mov ah,09h
- int 10h
- ret
- PUTCHAR ENDP
-
- ;
- ; Draw one line of INTERCOM's screen window
- ;
- LINE PROC NEAR
- push bx
- push bx
- push ax
- push bx
-
- MOVE_CURSOR bh,ICOL ; move to beginning of line
- PUTC al,1 ; display leading character
-
- pop bx ; retrieve row
- MOVE_CURSOR bh,ICOL+1 ; move to 2nd char of line
- pop ax ; retrieve char to display
- mov al,ah ; move char to al
- PUTC al,IWIDTH-2 ; display line 'middle' character
-
- pop bx ; retrieve row coords
- MOVE_CURSOR bh,ICOL+IWIDTH-1; move to last char of line
- pop ax ; retrieve character
- PUTC al,1 ; display line 'end' character
-
- ret
-
- LINE ENDP
-
-
-
- LAST_BYTE EQU $
-
- ;
- ; Initialization -- thrown away after load
- ;
-
- title1 db " SoftMagic Resident Intercom V1.0 for LANtastic",13,10,0
- title2 db "Copyright 1989 by SoftMagic, Inc. All rights Reserved.",13,10,0
- title3 db " LANtastic is a trademark of Artisoft, Inc.",13,10,0
- title4 db 13,10,"The SoftMagic Resident Intercom is already installed.",13,10,0
-
- IFDEF SHAREWARE
- title5 db 7,"Thanks for trying this unregistered ShareWare Version!",7,7,13,10,0
- ENDIF
-
- init: mov cs:busy,1 ; prevent activation
- @NewStack ; Set up local stack
-
- ; Display title messge
- mov di,OFFSET title1
- call PRT_STR
- mov di,OFFSET title2
- call PRT_STR
- mov di,OFFSET title3
- call PRT_STR
-
- IFDEF SHAREWARE
- mov di,OFFSET title5
- call PRT_STR
- ENDIF
-
-
- ;
- ; Get the location of the DOS Busy flag
- ;
- ; mov ax,3400h ; Flag is zero if DOS is safe
- ; int 21h
- ; mov dos_busy_seg,es
- ; mov dos_busy_offs,bx
-
- ;
- ; Replace the keyboard interrupt handler
- ;
- mov ah,35h ; Get int vector fcn.
- mov al,VECTOR1 ; vector to get
- int 21h ; Get the silly thing
-
- ; Save the old vector
-
- mov word ptr old_vector1,bx ; Save location of old vector
- mov word ptr old_vector1+2,es
- ;
- ; Set Interrupt vector to our routine
- ;
- mov ah,25h ; Set vector fcn
- mov al,VECTOR1 ; Vector to replace
- mov dx,OFFSET INT09_entry ; Pointer to our routine
- int 21h ; Replace the vector
-
- ;
- ; Replace LANtastic's internal DOS free vector
- ;
- MOV AX,5FE0H
- INT 21H ; GET THE DOS FREE VECTOR
- MOV WORD PTR old_vector2,BX
- MOV WORD PTR old_vector2+2,ES
-
- ;
- ; Set vector to our routine
- ;
- push cs
- pop es
- MOV BX,OFFSET DOSFREE
- MOV AX,5FE1H
- INT 21H
-
- ; Terminate and stay resident
- @OldStack ; Restore caller's stack
- mov cs:busy, 0 ; Enable pop-up
- mov dx,(offset LAST_BYTE - SEG_ORG + 15) shr 4
- mov ah,31h ; free memory and leave
- int 21h
- main ENDP
- msv ENDS
- END start
-